from django.db import models
from django.utils import timezone
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver

class ExperimentStatistics(models.Model):
    """试验统计模型"""
    
    # 试验类型选择
    EXPERIMENT_TYPE_CHOICES = [
        ('振动试验', '振动试验'),
        ('真空热试验', '真空热试验'),
        ('EMC试验', 'EMC试验'),
        ('磁试验', '磁试验'),
        ('常压试验', '常压试验'),
    ]
    
    # 试验类型字段
    experiment_type = models.CharField(
        max_length=20,
        choices=EXPERIMENT_TYPE_CHOICES,
        default='振动试验',
        verbose_name='试验类型'
    )
    
    # 基本信息
    experiment_number = models.CharField(max_length=100, verbose_name='试验编号')
    experiment_name = models.CharField(max_length=200, verbose_name='试验名称')
    product_type = models.CharField(max_length=100, verbose_name='参试产品类型', default='')
    test_items = models.CharField(max_length=100, verbose_name='试验项目')
    test_equipment = models.CharField(max_length=200, verbose_name='试验设备')
    experiment_commander = models.CharField(max_length=100, verbose_name='试验指挥')
    participants = models.TextField(verbose_name='参试人员')
    
    # 协外试验信息
    is_external_collaboration = models.CharField(
        max_length=10, 
        choices=[('是', '是'), ('否', '否')], 
        default='否',
        verbose_name='是否为协外试验'
    )
    test_company = models.CharField(max_length=200, verbose_name='送试方部门/公司')
    test_contact = models.CharField(max_length=200, verbose_name='送试方联系人及电话')
    
    # 产品信息
    participant_name = models.CharField(max_length=200, verbose_name='参试产品名称')
    product_quantity = models.CharField(max_length=50, verbose_name='参试产品数量')
    product_number = models.CharField(max_length=100, verbose_name='参试产品编号')
    
    # 时间信息
    product_entry_date = models.DateField(verbose_name='产品入场日期')
    test_start_date = models.DateField(verbose_name='试验开始日期')
    test_end_date = models.DateField(verbose_name='试验结束日期')
    product_exit_date = models.DateField(verbose_name='产品出场日期')
    operating_days = models.CharField(max_length=50, blank=True, verbose_name='开机天数')
    
    # 审批和文档信息
    reservation_approval_number = models.CharField(max_length=100, verbose_name='试验预约审批编号')
    photo_uploaded = models.CharField(
        max_length=10, 
        choices=[('是', '是'), ('否', '否')], 
        default='否',
        verbose_name='试验照片是否上传'
    )
    summary_report = models.CharField(max_length=200, verbose_name='总结报告/证明书')
    certificate_number = models.CharField(max_length=100, verbose_name='证书归档编号')
    
    # 合同和联系人信息
    contract_number = models.CharField(max_length=100, blank=True, verbose_name='合同编号')
    partner_contact = models.CharField(max_length=200, blank=True, verbose_name='合作方联系人')
    our_contact = models.CharField(max_length=200, blank=True, verbose_name='我方联系人')
    
    # 关联字段
    experiment_plan = models.ForeignKey(
        'experiment_planning.ExperimentPlan',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        verbose_name='关联试验计划'
    )
    
    # 系统字段
    created_at = models.DateTimeField(default=timezone.now, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    
    class Meta:
        db_table = 'experiment_statistics'
        verbose_name = '试验统计'
        verbose_name_plural = '试验统计'
        ordering = ['-created_at']
    
    def generate_experiment_number(self):
        """根据试验类型自动生成试验编号"""
        from datetime import datetime
        
        current_year = datetime.now().year
        category_prefixes = {
            '振动试验': 'SYZX-ZD',
            '真空热试验': 'SYZX-ZKR',
            'EMC试验': 'SYZX-EMC',
            '磁试验': 'SYZX-CSY',
            '常压试验': 'SYZX-CYR'
        }
        
        prefix = category_prefixes.get(self.experiment_type)
        if not prefix:
            return ''
        
        # 获取当前分类和年份的所有试验编号
        existing_experiments = ExperimentStatistics.objects.filter(
            experiment_type=self.experiment_type,
            experiment_number__contains=f'{prefix}-{current_year}'
        ).exclude(id=self.id if self.id else None)  # 排除当前记录（更新时）
        
        # 提取编号并找到最大值
        max_number = 0
        import re
        pattern = re.compile(rf'{re.escape(prefix)}-{current_year}-(\d+)')
        
        for exp in existing_experiments:
            if exp.experiment_number:
                match = pattern.search(exp.experiment_number)
                if match:
                    num = int(match.group(1))
                    if num > max_number:
                        max_number = num
        
        # 生成新编号
        new_number = str(max_number + 1).zfill(3)
        return f'{prefix}-{current_year}-{new_number}'
    
    def save(self, *args, **kwargs):
        """保存时自动生成试验编号（如果为空）"""
        if not self.experiment_number:
            self.experiment_number = self.generate_experiment_number()
        super().save(*args, **kwargs)
    
    @classmethod
    def reorder_experiment_numbers(cls, experiment_type):
        """重新排序指定类型的试验编号，确保编号连续"""
        from datetime import datetime
        
        current_year = datetime.now().year
        category_prefixes = {
            '振动试验': 'SYZX-ZD',
            '真空热试验': 'SYZX-ZKR',
            'EMC试验': 'SYZX-EMC',
            '磁试验': 'SYZX-CSY',
            '常压试验': 'SYZX-CYR'
        }
        
        prefix = category_prefixes.get(experiment_type)
        if not prefix:
            return
        
        # 获取当前分类和年份的所有试验，按创建时间排序
        experiments = cls.objects.filter(
            experiment_type=experiment_type,
            experiment_number__contains=f'{prefix}-{current_year}'
        ).order_by('created_at')
        
        # 重新分配编号
        for index, experiment in enumerate(experiments, 1):
            new_number = f'{prefix}-{current_year}-{str(index).zfill(3)}'
            if experiment.experiment_number != new_number:
                experiment.experiment_number = new_number
                # 使用update避免触发save方法的递归调用
                cls.objects.filter(id=experiment.id).update(experiment_number=new_number)
    
    def __str__(self):
        return f"{self.experiment_number} - {self.experiment_name}"

class ExperimentAttachment(models.Model):
    """试验附件模型"""
    
    experiment = models.ForeignKey(
        ExperimentStatistics, 
        on_delete=models.CASCADE, 
        related_name='attachments',
        verbose_name='关联试验'
    )
    name = models.CharField(max_length=255, verbose_name='文件名')
    size = models.BigIntegerField(verbose_name='文件大小')
    file_type = models.CharField(max_length=100, verbose_name='文件类型')
    content = models.BinaryField(blank=True, null=True, verbose_name='文件内容')
    upload_time = models.DateTimeField(default=timezone.now, verbose_name='上传时间')
    
    class Meta:
        db_table = 'experiment_attachments'
        verbose_name = '试验附件'
        verbose_name_plural = '试验附件'
        ordering = ['-upload_time']
    
    def __str__(self):
        return f"{self.experiment.experiment_number} - {self.name}"


# 信号处理器：监听ExperimentPlan变化并自动同步到ExperimentStatistics
@receiver(post_save, sender='experiment_planning.ExperimentPlan')
def sync_experiment_plan_to_statistics(sender, instance, created, **kwargs):
    """
    当ExperimentPlan创建或更新时，自动同步到ExperimentStatistics
    只同步is_adjustable为True的数据
    """
    if not instance.is_adjustable:
        return
    
    # 根据设备的experiment字段判断试验类型
    def get_experiment_type_by_equipment(equipment):
        if not equipment:
            return None  # 没有设备时返回None，不设置默认试验类型
        
        experiment_type = equipment.experiment.lower()
        if '振动' in experiment_type:
            return '振动试验'
        elif '真空' in experiment_type or '热' in experiment_type:
            return '真空热试验'
        elif 'emc' in experiment_type or '电磁' in experiment_type:
            return 'EMC试验'
        elif '磁' in experiment_type:
            return '磁试验'
        else:
            return '常压试验'
    
    # 获取试验类型，如果为None则跳过同步
    experiment_type = get_experiment_type_by_equipment(instance.equipment)
    if experiment_type is None:
        return  # 没有设备或无法确定试验类型时，跳过同步
    
    # 获取或创建ExperimentStatistics记录
    experiment_stats, created = ExperimentStatistics.objects.get_or_create(
        experiment_plan=instance,
        defaults={
            'experiment_type': experiment_type,
            'experiment_number': '',  # 留空，让save方法自动生成
            'experiment_name': instance.experiment_report_name or '',
            'product_type': instance.experiment_type or '',
            'test_equipment': instance.equipment.name if instance.equipment else '',
            'test_company': instance.depart or '',
            'product_entry_date': instance.enter_date,
            'test_start_date': instance.start_date,
            'test_end_date': instance.complete_date,
            'product_exit_date': instance.end_date,
            'reservation_approval_number': instance.bid or '',
            # 设置默认值
            'test_items': '',
            'experiment_commander': '',
            'participants': '',
            'test_contact': '',
            'participant_name': '',
            'product_quantity': '',
            'product_number': '',
            'operating_days': '',
            'photo_uploaded': '否',
            'summary_report': '',
            'certificate_number': '',
            'contract_number': '',
            'partner_contact': '',
            'our_contact': '',
        }
    )
    
    # 如果记录已存在，更新相关字段
    if not created:
        experiment_stats.experiment_type = experiment_type
        experiment_stats.experiment_name = instance.experiment_report_name or ''
        experiment_stats.product_type = instance.experiment_type or ''
        experiment_stats.test_equipment = instance.equipment.name if instance.equipment else ''
        experiment_stats.test_company = instance.depart or ''
        experiment_stats.product_entry_date = instance.enter_date
        experiment_stats.test_start_date = instance.start_date
        experiment_stats.test_end_date = instance.complete_date
        experiment_stats.product_exit_date = instance.end_date
        experiment_stats.reservation_approval_number = instance.bid or ''
        experiment_stats.save()


@receiver(post_delete, sender='experiment_planning.ExperimentPlan')
def delete_experiment_statistics(sender, instance, **kwargs):
    """
    当ExperimentPlan被删除时，同时删除对应的ExperimentStatistics记录
    """
    try:
        experiment_stats = ExperimentStatistics.objects.get(experiment_plan=instance)
        experiment_type = experiment_stats.experiment_type
        experiment_stats.delete()
        # 删除后重新排序编号
        ExperimentStatistics.reorder_experiment_numbers(experiment_type)
    except ExperimentStatistics.DoesNotExist:
        pass  # 如果不存在对应记录，忽略


@receiver(post_delete, sender=ExperimentStatistics)
def reorder_after_delete(sender, instance, **kwargs):
    """
    当ExperimentStatistics记录被直接删除时，重新排序编号
    """
    ExperimentStatistics.reorder_experiment_numbers(instance.experiment_type)
